package svc.elib.analysis;

import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;

import jsc.correlation.KendallCorrelation;
import jsc.datastructures.PairedData;

import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
import org.apache.commons.math3.stat.correlation.SpearmansCorrelation;

import svc.elib.db.Author;
import svc.elib.db.Database;
import svc.elib.socnet.CentralityMetrics;
import svc.elib.socnet.ConnectedComponents;
import svc.elib.socnet.EvolutionarySnapshots;
import svc.elib.socnet.Net;
import svc.elib.socnet.SocConstructor;

public class ImportantFigures {

	private Net[] snaps;
	private int startYear;
	
	public static class AuthorMetrics implements Comparable<AuthorMetrics> {
		double now;
		double next;
		
		public AuthorMetrics(double now, double next) {
			this.now = now;
			this.next = next;
		}

		@Override
		public int compareTo(AuthorMetrics arg0) {
			double diff = this.now - arg0.now;
			if (diff > 0)
				return -1;
			else
			if (diff < 0)
				return 1;
			else
				return 0;
		}
		
		public String toString() {
			return now + ", " + next;
		}
	}
	
	public ImportantFigures(Net net) {
		EvolutionarySnapshots es = new EvolutionarySnapshots(net);
		snaps = es.getSnapshots();
		startYear = es.getStartYear();
	}
	
	public void stabilityOfBetweenessTopAuthors(boolean considerWeight) {
		for (int i = 0; i < snaps.length - 1; i++) {
			int year = startYear + i + 1;
			Net current = snaps[i];
			CentralityMetrics cmCurrent = new CentralityMetrics(current);
			cmCurrent.computeBetweeness(considerWeight);
			
			Net next = snaps[i+1];
			//Net next = snaps[i + 10];
			CentralityMetrics cmNext = new CentralityMetrics(next);
			cmNext.computeBetweeness(considerWeight);
			
			Iterator<Author> ait = current.getGraph().getVertices().iterator();
			LinkedList<AuthorMetrics> lam = new LinkedList<AuthorMetrics>();
			double mSum = 0;
			while (ait.hasNext()) {
				Author a = ait.next();
				double b1 = cmCurrent.getBetweenness(a.getName());
				double b2 = cmNext.getBetweenness(a.getName());
				mSum += b1;
				lam.add(new AuthorMetrics(b1, b2));
			}
			
			if (mSum < 1)
				continue;
			
			Collections.sort(lam);
			
			// determine top 5%
			int endIndex = (int) ((double) lam.size() * 0.05);
			
			/*
			double localSum = 0;
			int endIndex = 0;
			while (localSum <= mSum / 2) {
				localSum += lam.get(endIndex).now;
				++endIndex;
			}
			--endIndex;
			
			if (endIndex < 2)
				continue;
			*/
			double seq1[] = new double[endIndex];
			double seq2[] = new double[endIndex];
			
			for (int j = 0; j < endIndex; j++) {
				seq1[j] = lam.get(j).now;
				seq2[j] = lam.get(j).next;
			}
			
			SpearmansCorrelation sc = new SpearmansCorrelation();
			double scc = sc.correlation(seq1, seq2);
			
			PearsonsCorrelation pc = new PearsonsCorrelation();
			double pcc = pc.correlation(seq1, seq2);
			
			KendallCorrelation kc = new KendallCorrelation(new PairedData(seq1, seq2));
			double kcc = kc.getTestStatistic();
			
			double fraction = (double) endIndex / (double) lam.size();
			System.out.println(year + ", " + scc + ", " + pcc + ", " + kcc + ", " + fraction + ", " + endIndex);
		}
	}
	
	private int yearToIndex(int year) {
		return year - startYear - 1;
	}
	
	public void stabilityOfBetweenessTopAuthorsFiveYears(boolean considerWeight) {
		for (int year = 1935; year < 2010; year += 5) {
			Net current = snaps[yearToIndex(year)];
			CentralityMetrics cmCurrent = new CentralityMetrics(current);
			cmCurrent.computeBetweeness(considerWeight);
			
			int nextYear = year + 5;
			if (nextYear == 2010)
				nextYear = 2011;
			
			Net next = snaps[yearToIndex(nextYear)];
			CentralityMetrics cmNext = new CentralityMetrics(next);
			cmNext.computeBetweeness(considerWeight);
			
			Iterator<Author> ait = current.getGraph().getVertices().iterator();
			LinkedList<AuthorMetrics> lam = new LinkedList<AuthorMetrics>();
			double mSum = 0;
			while (ait.hasNext()) {
				Author a = ait.next();
				double b1 = cmCurrent.getBetweenness(a.getName());
				double b2 = cmNext.getBetweenness(a.getName());
				mSum += b1;
				lam.add(new AuthorMetrics(b1, b2));
			}
			
			if (mSum < 1)
				continue;
			
			Collections.sort(lam);
			
			// determine top 5%
			int endIndex = (int) ((double) lam.size() * 0.05);
			
			/*
			double localSum = 0;
			int endIndex = 0;
			while (localSum <= mSum / 2) {
				localSum += lam.get(endIndex).now;
				++endIndex;
			}
			--endIndex;
			
			if (endIndex < 2)
				continue;
			*/
			double seq1[] = new double[endIndex];
			double seq2[] = new double[endIndex];
			
			for (int j = 0; j < endIndex; j++) {
				seq1[j] = lam.get(j).now;
				seq2[j] = lam.get(j).next;
			}
			
			SpearmansCorrelation sc = new SpearmansCorrelation();
			double scc = sc.correlation(seq1, seq2);
			
			PearsonsCorrelation pc = new PearsonsCorrelation();
			double pcc = pc.correlation(seq1, seq2);
			
			KendallCorrelation kc = new KendallCorrelation(new PairedData(seq1, seq2));
			double kcc = kc.getTestStatistic();
			
			double fraction = (double) endIndex / (double) lam.size();
			System.out.println(year + " -- " + nextYear + ", " + scc + ", " + pcc + ", " + kcc + ", " + fraction + ", " + endIndex);
		}
	}
	
	public void stabilityOfDegreeTopAuthors() {
		for (int i = 0; i < snaps.length - 1; i++) {
			int year = startYear + i + 1;
			Net current = snaps[i];
			Net next = snaps[i+1];
			
			Iterator<Author> ait = current.getGraph().getVertices().iterator();
			LinkedList<AuthorMetrics> lam = new LinkedList<AuthorMetrics>();
			double mSum = 0;
			while (ait.hasNext()) {
				Author a = ait.next();
				double b1 = current.getGraph().degree(a);
				double b2 = next.getGraph().degree(a);
				mSum += b1;
				lam.add(new AuthorMetrics(b1, b2));
			}
			
			if (mSum < 1)
				continue;
			
			Collections.sort(lam);
			
			// determine top 5%
			int endIndex = (int) ((double) lam.size() * 0.05);
			/*
			double localSum = 0;
			int endIndex = 0;
			while (localSum <= mSum / 2) {
				localSum += lam.get(endIndex).now;
				++endIndex;
			}
			--endIndex;
			*/
			
			if (endIndex < 2)
				continue;
		
			double seq1[] = new double[endIndex];
			double seq2[] = new double[endIndex];
			
			for (int j = 0; j < endIndex; j++) {
				seq1[j] = lam.get(j).now;
				seq2[j] = lam.get(j).next;
			}
			
			SpearmansCorrelation sc = new SpearmansCorrelation();
			double scc = sc.correlation(seq1, seq2);
			
			PearsonsCorrelation pc = new PearsonsCorrelation();
			double pcc = pc.correlation(seq1, seq2);
			
			KendallCorrelation kc = new KendallCorrelation(new PairedData(seq1, seq2));
			double kcc = kc.getTestStatistic();
			
			double fraction = (double) endIndex / (double) lam.size();
			System.out.println(year + ", " + scc + ", " + pcc + ", " + kcc + ", " + fraction + ", " + endIndex);
		}
	}
	
	public void stabilityOfBetweeness(boolean considerWeight) {
		for (int i = 0; i < snaps.length - 1; i++) {
			int year = startYear + i + 1;
			Net current = snaps[i];
			CentralityMetrics cmCurrent = new CentralityMetrics(current);
			cmCurrent.computeBetweeness(considerWeight);
			
			Net next = snaps[i+1];
			CentralityMetrics cmNext = new CentralityMetrics(next);
			cmNext.computeBetweeness(considerWeight);
			
			Iterator<Author> ait = current.getGraph().getVertices().iterator();
			
			double seq1[] = new double[current.getNumAuthors()];
			double seq2[] = new double[current.getNumAuthors()];
			int scnt = 0;
			
			while (ait.hasNext()) {
				Author a = ait.next();
				double b1 = cmCurrent.getBetweenness(a.getName());
				double b2 = cmNext.getBetweenness(a.getName());
				seq1[scnt] = b1;
				seq2[scnt] = b2;
				++scnt;
			}
			
			SpearmansCorrelation sc = new SpearmansCorrelation();
			double scc = sc.correlation(seq1, seq2);
			
			PearsonsCorrelation pc = new PearsonsCorrelation();
			double pcc = pc.correlation(seq1, seq2);
			
			KendallCorrelation kc = new KendallCorrelation(new PairedData(seq1, seq2));
			double kcc = kc.getTestStatistic();
			
			System.out.println(year + ", " + scc + ", " + pcc + ", " + kcc);
		}
	}
	
	public void stabilityOfDegree() {
		for (int i = 0; i < snaps.length - 1; i++) {
			int year = startYear + i + 1;
			Net current = snaps[i];
			Net next = snaps[i+1];
			double seq1[] = new double[current.getNumAuthors()];
			double seq2[] = new double[current.getNumAuthors()];
			int scnt = 0;
			Iterator<Author> ait = current.getGraph().getVertices().iterator();
			while (ait.hasNext()) {
				Author a = ait.next();
				
				seq1[scnt] = current.getGraph().degree(a);
				seq2[scnt] = next.getGraph().degree(a);
				++scnt;
			}
			
			SpearmansCorrelation sc = new SpearmansCorrelation();
			double scc = sc.correlation(seq1, seq2);
			
			PearsonsCorrelation pc = new PearsonsCorrelation();
			double pcc = pc.correlation(seq1, seq2);
			
			KendallCorrelation kc = new KendallCorrelation(new PairedData(seq1, seq2));
			double kcc = kc.getTestStatistic();
			
			System.out.println(year + ", " + scc + ", " + pcc + ", " + kcc);
		}
	}
	
	public void stabilityOfCC() {
		for (int i = 0; i < snaps.length - 1; i++) {
			int year = startYear + i + 1;
			Net current = snaps[i];
			Net next = snaps[i+1];
			double seq1[] = new double[current.getNumAuthors()];
			double seq2[] = new double[current.getNumAuthors()];
			int scnt = 0;
			Iterator<Author> ait = current.getGraph().getVertices().iterator();
			while (ait.hasNext()) {
				Author a = ait.next();
				
				seq1[scnt] = current.getCC(a);
				seq2[scnt] = next.getCC(a);
				++scnt;
			}
			
			SpearmansCorrelation sc = new SpearmansCorrelation();
			double scc = sc.correlation(seq1, seq2);
			
			PearsonsCorrelation pc = new PearsonsCorrelation();
			double pcc = pc.correlation(seq1, seq2);
			
			KendallCorrelation kc = new KendallCorrelation(new PairedData(seq1, seq2));
			double kcc = kc.getTestStatistic();
			
			System.out.println(year + ", " + scc + ", " + pcc + ", " + kcc);
		}
	}
	
	public void runStabilityAnalysis() {
		System.out.println("Stability of betweeness [weight considered]");
		stabilityOfBetweeness(true);
		
		System.out.println("\n\nStability of betweeness [weight ignored]");
		stabilityOfBetweeness(false);
		
		System.out.println("\n\nStability of degree");
		stabilityOfDegree();
		
		System.out.println("\n\nStability of CC");
		stabilityOfCC();
	}
	
	public static void main(String[] args) 
		throws IOException
	{
		Database db = new Database("eLibData.csv", 1932, 2011);
		System.out.println(db.info());
		SocConstructor soc = new SocConstructor(db);
		Net net = soc.getNet();
		
		/*
		ConnectedComponents cs = new ConnectedComponents(net);
		cs.resolveComponents();
		Net largest = cs.getComponents().get(0);
		
		ImportantFigures impfig = new ImportantFigures(net);
		impfig.runStabilityAnalysis();
		
		System.out.println("\n\n\n Stability analysis for the largest component... ");
		impfig = new ImportantFigures(largest);
		impfig.runStabilityAnalysis();
		
		
		ImportantFigures impf = new ImportantFigures(net);
		//impf.stabilityOfDegreeTopAuthors(true);
		System.out.println("Stability of betweeness, top 5% authors, weight ingored");
		impf.stabilityOfBetweenessTopAuthors(false);
		
		System.out.println("Stability of betweeness, top 5% authors, weight included");
		impf.stabilityOfBetweenessTopAuthors(true);
		
		System.out.println("Stability of degree, top 5% authors");
		impf.stabilityOfDegreeTopAuthors();
		*/
		
		ImportantFigures impf = new ImportantFigures(net);
		impf.stabilityOfBetweenessTopAuthorsFiveYears(false);
	}
}
